package pl.edu.mimuw.irs.core.model.petrinet;

import pl.edu.mimuw.irs.core.exception.InternalException;
import pl.edu.mimuw.irs.core.exception.InternalException.Cause;
import pl.edu.mimuw.irs.core.util.Position;

/**
 * @author Jakub Rauch
 * Created on: 2009-05-07
 */
public class Place extends Node {
	//private static Logger logger = Logger.getLogger(Place.class);
	
	// *** Attributes
	
	// Place can contain unlimited number of tokens.
	private int tokens;
	// Getters and setters
	public int getTokens() {
		return tokens;
	}
	public void setTokens(int tokens) {
		this.tokens = tokens;
	}
	
	// *** Methods
	
	public Place(String id, Position position, int tokens) {
		setId(id);
		setPosition(position);
		setTokens(tokens);
	}

	public Place(String id, Position position) {
		this(id, position, 0);
	}
	
	public Place(Position position) {
		this(getNewId(), position);
	}
	
	public Place(String id, int tokens) {
		this(id, new Position(), tokens);
	}
	
	public Place(String id) {
		this(id, new Position());
	}

	public Place() {
		this((String)null);
	}
	
	/**
	 * Removes num tokens from this place.
	 * @param num
	 */
	public void removeTokens(int num) {
		if (num > tokens) throw new InternalException(Cause.PETRI_NET_NEGATIVE_TOKEN);
		
		setTokens(getTokens() - num);
	}
	
	/**
	 * Puts num tokens to this place.
	 * @param num
	 */
	public void addTokens(int num) {
		setTokens(getTokens() + num);
	}
	
	@Override
	public void addArc(Arc arc) {
		switch (arc.getDirection()) {
			case PLACE_TRANSITION:
				getOutgoingArcs().add(arc);
				break;
			case TRANSITION_PLACE:
				getIncomingArcs().add(arc);
				break;
			default:
				throw new InternalException(Cause.PETRI_NET_UNKNOWN_ARC_DIRECTION);
		}
	}
	
	@Override
	public void removeArc(Arc arc) {
		switch (arc.getDirection()) {
			case PLACE_TRANSITION:
				getOutgoingArcs().remove(arc);
				break;
			case TRANSITION_PLACE:
				getIncomingArcs().remove(arc);
				break;
			default:
				throw new InternalException(Cause.PETRI_NET_UNKNOWN_ARC_DIRECTION);
		}
	}
	
	public void connect(Transition transition) {
		getNet().addPlaceTranArc(this.getId(), transition.getId());
	}
	
	@Override
	public void destroy() {
		for (Arc incomingArc : getIncomingArcs()) {
			incomingArc.getTransition().removeArc(incomingArc);
		}
		
		for (Arc outgoingArc : getOutgoingArcs()) {
			outgoingArc.getTransition().removeArc(outgoingArc);
		}
	}
}
